#include "TestOpenGL.h"

TestOpenGL::TestOpenGL(QWidget *parent) : MonWidgetGL(60, parent, "Premier Polygone avec OpenGL et Qt")
{
}

void TestOpenGL::initializeGL()
{
    f_x = 0.0;
    loadTexture("pic/box.png");

    glEnable(GL_TEXTURE_2D);
    glShadeModel(GL_SMOOTH);

    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    glClearDepth(1.0f);

    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LEQUAL);

    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

    //////////////////////////////////
    nbFaces = 0;
}

void TestOpenGL::resizeGL(int width, int height)
{
    if(height == 0)
        height = 1;
    glViewport(0, 0, width, height);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45.0f, (GLfloat)width/(GLfloat)height, 0.1f, 100.0f);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

void TestOpenGL::paintGL()
{
    f_x += 0.3;
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();

    glTranslatef(-1.5f, 0.0f, -6.0f);
    //glRotatef(f_x, 0.0, 1.0, 0.0);

    glBindTexture(GL_TEXTURE_2D, texture[0]);

    glColor3f(0.0f, 1.0f, 0.0f);

    if(nbFaces) glDrawElements(GL_TRIANGLES, nbFaces*3,GL_UNSIGNED_INT, faces);

    glTranslated(X, Y, Z);

    glBegin(GL_QUADS);
    // Face Avant
    glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f);
    glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f);
    glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f,  1.0f);
    glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f,  1.0f);
    // Face Arrière
    glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
    glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f);
    glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f);
    glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
    // Face Haut
    glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f);
    glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f,  1.0f,  1.0f);
    glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f,  1.0f,  1.0f);
    glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f);
    // Face Bas
    glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
    glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
    glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f);
    glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f);
    // Face Droite
    glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
    glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f);
    glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f,  1.0f,  1.0f);
    glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f);
    // Face Gauche
    glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
    glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f);
    glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f,  1.0f,  1.0f);
    glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f);
    glEnd();
}

void TestOpenGL::loadTexture(QString textureName)
{
    QImage qim_Texture;
    QImage qim_TempTexture;
    qim_TempTexture.load(textureName);
    qim_Texture = QGLWidget::convertToGLFormat( qim_TempTexture );
    glGenTextures( 1, &texture[0] );
    glBindTexture( GL_TEXTURE_2D, texture[0] );
    glTexImage2D( GL_TEXTURE_2D, 0, 3, qim_Texture.width(), qim_Texture.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, qim_Texture.bits() );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
}

void TestOpenGL::keyPressEvent(QKeyEvent *keyEvent)
{
    switch(keyEvent->key())
    {
    case Qt::Key_Q:
        X-=1;
        break;
    case Qt::Key_D:
        X+=1;
        break;
    case Qt::Key_Z:
        Y+=1;
        break;
    case Qt::Key_S:
        Y-=1;
        break;
    case Qt::Key_F1:
        toggleFullWindow();
        break;
    case Qt::Key_P:
        lireFichier("../maillages/triceratops.off");
        break;
    }
    paintGL();
}


void TestOpenGL::lireFichier(const char * chemin)
{
  FILE * file = fopen(chemin, "r");
  char s[50];
  int nbPoints = 0;
  int zero = 0;
  float X3, Y3, Z3;
  int X2, Y2, Z2;
  if(file != NULL)
    {
      fscanf(file, "%s", s);
      if(strcmp(s, "OFF") == 0)
        {
          fscanf(file, "%d%d%d", &nbPoints, &nbFaces, &zero);
          //cout<<"nombre de points : "<<nbPoints<<"\n";
          //cout<<"nombre de faces : "<<nbFaces<<"\n";
          //cout<<"zéro : "<<zero<<"\n";
          if(points) delete [] points;
          points = new GLfloat[3*nbPoints];
          for(int i = 0; i < nbPoints; ++i)
            {
              fscanf(file, "%f%f%f", &X3, &Y3, &Z3);
              //cout<<X3<<" "<<Y3<<" "<<Z3<<"\n";
              points[3*i] = X3;
              points[3*i + 1] = Y3;
              points[3*i + 2] = Z3;
            }
          glVertexPointer(3, GL_FLOAT, 0, points);
          if(faces) delete [] faces;
          faces = new GLuint[3*nbFaces];
          for(int i = 0; i < nbFaces; ++i)
            {
              fscanf(file, "%d%d%d%d", &zero, &X2, &Y2, &Z2);
              //cout<<X<<" "<<Y<<" "<<Z<<"\n";
              faces[3*i] = X2;
              faces[3*i + 1] = Y2;
              faces[3*i + 2] = Z2;
            }

        }
    }
}

void TestOpenGL::lireFichierTerrain(const char *chemin)
{
  FILE * file = fopen(chemin, "r");
  //FILE * file2 = fopen("test.off", "w");
  int nbColonnes;
  int nbLignes;
  int nbPoints;
  int onSenFou;
  int distanceDeuxPoints;
  int noData;
  GLfloat ZTerrain;
  char s[50];
  if(file != NULL)
    {
      //cout<<"Fichier terrain trouvé.\n";
      fscanf(file, "%s%d", s, &nbColonnes);
      //cout<<s<<": "<<nbColonnes<<'\n';
      fscanf(file, "%s%d", s, &nbLignes);
      //cout<<s<<": "<<nbLignes<<'\n';
      nbPoints = nbColonnes*nbLignes;
      //cout<<"nbPoints: "<<nbPoints<<"\n";
      nbFacesTerrain = (nbColonnes) * (nbLignes);
      //fprintf(file2, "OFF");
      //fprintf(file2, "%d%d%d", nbPoints, nbPoints, 0);
      fscanf(file, "%s%d", s, &onSenFou);
      fscanf(file, "%s%d", s, &onSenFou);
      fscanf(file, "%s%d", s, &distanceDeuxPoints);
      //cout<<s<<": "<<distanceDeuxPoints<<'\n';
      fscanf(file, "%s%d", s, &noData);
      //cout<<s<<": "<<noData<<'\n';
      if(pointsTerrain) delete []pointsTerrain;
      pointsTerrain = new GLfloat[3*nbPoints];

      for(int i = 0; i < nbLignes; i++)
        {
          GLfloat I = i;
          for(int j = 0; j < nbColonnes; ++j)
            {
              GLfloat J = j;
              fscanf(file, "%f", &ZTerrain);
              pointsTerrain[3*(i*nbColonnes+j)] = I;
              pointsTerrain[3*(i*nbColonnes+j) + 1] = J;
              pointsTerrain[3*(i*nbColonnes+j) + 2] = ZTerrain;
            }
        }

      glVertexPointer(3, GL_FLOAT, 0, pointsTerrain);

      if(facesTerrain) delete []facesTerrain;
      facesTerrain = new GLuint[3*nbPoints];
      for(int i = 0; i < nbColonnes-1; ++i)
        {
          for(int j = 0; j < nbLignes-1; ++j)
            {
              facesTerrain[3*(i*nbColonnes+j)] = (i*nbColonnes+j);
              facesTerrain[3*(i*nbColonnes+j) + 1] = (i*nbColonnes + j) + 1;
              facesTerrain[3*(i*nbColonnes+j) + 2] = (i*nbColonnes + j) + nbColonnes;
            }
        }
      //for(int i = 0; i < 3*nbPoints; ++i)
      //{
      //if(!(i%3))cout<<endl;
      //cout<<i<<": "<<facesTerrain[i]<<" ";
      //}
    }
  else
    {
      //cout<<"Fichier terrain non trouvé.\n";
    }
}
